package com.whfc.fvs.service.impl;

import com.whfc.common.enums.DelFlag;
import com.whfc.common.exception.BizException;
import com.whfc.common.result.ListData;
import com.whfc.common.result.ResultEnum;
import com.whfc.common.vs.imou.ImouApi;
import com.whfc.common.vs.imou.constant.ImouConstant;
import com.whfc.common.vs.imou.entity.ImouChannelInfo;
import com.whfc.common.vs.imou.entity.ImouDeviceInfo;
import com.whfc.common.vs.imou.entity.ImouStreamInfo;
import com.whfc.fvs.dao.FvsDeviceMapper;
import com.whfc.fvs.dao.FvsStreamMapper;
import com.whfc.fvs.dto.*;
import com.whfc.fvs.entity.FvsDevice;
import com.whfc.fvs.entity.FvsStream;
import com.whfc.fvs.enums.FvsDevicePtzOption;
import com.whfc.fvs.enums.FvsDeviceType;
import com.whfc.fvs.enums.VsPlatform;
import com.whfc.fvs.param.FvsDeviceAddParam;
import com.whfc.fvs.service.FvsPlatformService;
import com.whfc.fvs.service.factroy.FvsPlatformConstant;
import com.whfc.fvs.service.manager.FvsTokenMgr;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 乐橙云 service
 *
 * @author qzexing
 * @version 1.0
 * @date 2020/4/29 23:50
 */
@Service(FvsPlatformConstant.IMOU_SERVICE)
public class FvsImouVsServiceImpl implements FvsPlatformService {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * 一天
     */
    private static final long ONE_DAY_MILLS = 24 * 60 * 60 * 1000;

    @Autowired
    private FvsDeviceMapper fvsDeviceMapper;

    @Autowired
    private FvsStreamMapper fvsStreamMapper;

    @Autowired
    private FvsTokenMgr fvsTokenMgr;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addDevice(FvsDeviceDTO fvsDeviceDTO, FvsDeviceAddParam deviceAddParam) {
        String deviceSerial = deviceAddParam.getUsername();
        if (StringUtils.isEmpty(deviceSerial)) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "设备序列号不能为空.");
        }
        Integer deviceType = deviceAddParam.getDeviceType();
        if (deviceType == null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "设备类型不能为空.");
        }
        FvsDeviceType type = FvsDeviceType.parseValue(deviceType);
        if (type == null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "设备类型错误.");
        }
        String password = deviceAddParam.getPassword();
        Integer deptId = fvsDeviceDTO.getDeptId();
        //获取Api
        ImouApi imouApi = getImouApi(deptId);
        //绑定大华设备
        String accessToken = fvsTokenMgr.getImouAccessToken(imouApi, deptId);
        imouApi.createDevice(accessToken, deviceSerial, password);
        //更新设备信息
        FvsDevice fvsDevice = new FvsDevice();
        fvsDevice.setId(fvsDeviceDTO.getId());
        fvsDevice.setUsername(deviceSerial);
        fvsDevice.setPassword(password);
        fvsDevice.setDeviceType(deviceType);
        fvsDevice.setPtz(1);
        fvsDeviceMapper.updateByPrimaryKeySelective(fvsDevice);
        //初始化通道信息
        initChannel(fvsDeviceDTO.getId(), imouApi, accessToken);
    }

    @Override
    public void deleteDevice(FvsDeviceDTO fvsDeviceDTO) {
        if (FvsDeviceType.DVR.getValue().equals(fvsDeviceDTO.getDeviceType())) {
            //如果当前设备是硬盘录像机
            del(fvsDeviceDTO);
            //逻辑删除硬盘录像机下面的所有摄像头
            fvsDeviceMapper.logicDeleteByPid(fvsDeviceDTO.getId());
        } else {
            if (0 == fvsDeviceDTO.getPid()) {
                //智能监控摄像头且并非在硬盘录像机下面
                del(fvsDeviceDTO);
            }
        }
    }

    @Override
    public String getSnapshotUrl(FvsDeviceDTO fvsDeviceDTO) {
        Integer deptId = fvsDeviceDTO.getDeptId();
        ImouApi imouApi = getImouApi(deptId);
        String accessToken = fvsTokenMgr.getImouAccessToken(imouApi, deptId);
        return imouApi.getSnapshotUrl(accessToken, fvsDeviceDTO.getUsername(), fvsDeviceDTO.getChannelNo());
    }

    @Override
    public FvsStreamDTO getStreamUrl(FvsDeviceDTO fvsDeviceDTO) {
        // 播放地址过期，需要重新获取
        Integer deptId = fvsDeviceDTO.getDeptId();
        ImouApi imouApi = getImouApi(deptId);
        String accessToken = fvsTokenMgr.getImouAccessToken(imouApi, deptId);
        String deviceSerial = fvsDeviceDTO.getUsername();
        Integer channelNo = fvsDeviceDTO.getChannelNo();
        FvsStream fvsStream = fvsStreamMapper.selectStreamByDeviceId(fvsDeviceDTO.getId());
        boolean isNeedRefresh = false;
        //没有视频播放地址
        if (fvsStream == null) {
            isNeedRefresh = true;
            fvsStream = new FvsStream();
        }
        //视频播放地址过期
        else {
            long timeDiff = fvsStream.getExpireTime().getTime() - System.currentTimeMillis();
            if (timeDiff < ONE_DAY_MILLS) {
                isNeedRefresh = true;
            }
        }
        if (isNeedRefresh) {
            ImouStreamInfo streamInfo = imouApi.getStreamUrl(accessToken, deviceSerial, channelNo);
            fvsStream.setDeviceId(fvsDeviceDTO.getId());
            fvsStream.setHls(streamInfo.getHls());
            fvsStream.setHlsHd(streamInfo.getHlsHd());
            fvsStream.setExpireTime(streamInfo.getExpireTime());
            fvsStream.setDelFlag(DelFlag.UNDELETE.getValue());
            fvsStreamMapper.insertOrUpdate(fvsStream);
        }
        FvsStreamDTO streamDTO = new FvsStreamDTO();
        BeanUtils.copyProperties(fvsStream, streamDTO);
        return streamDTO;
    }

    @Override
    public ListData<FvsRecordDTO> getRecordList(FvsDeviceDTO fvsDeviceDTO, Date startTime, Date endTime) {
        ListData<FvsRecordDTO> listData = new ListData<>();
        List<FvsRecordDTO> list = new ArrayList<>();

        Integer deptId = fvsDeviceDTO.getDeptId();
        ImouApi imouApi = getImouApi(deptId);
        String accessToken = fvsTokenMgr.getImouAccessToken(imouApi, deptId);
        String recordUrl = imouApi.getRecordList(accessToken, fvsDeviceDTO.getUsername(),
                fvsDeviceDTO.getChannelNo(), startTime, endTime);
        if (StringUtils.isNotBlank(recordUrl)) {
            FvsRecordDTO appFvsRecordDTO = new FvsRecordDTO();
            appFvsRecordDTO.setFileFormat("hls");
            appFvsRecordDTO.setRecordUrl(recordUrl);
            appFvsRecordDTO.setStartTime(startTime);
            appFvsRecordDTO.setEndTime(endTime);
            list.add(appFvsRecordDTO);
        }
        listData.setList(list);
        return listData;
    }

    @Override
    public void ptz(FvsDeviceDTO fvsDeviceDTO, FvsDevicePtzOption devicePtzOption) {
        ImouApi imouApi = getImouApi(fvsDeviceDTO.getDeptId());
        String accessToken = fvsTokenMgr.getImouAccessToken(imouApi, fvsDeviceDTO.getDeptId());
        imouApi.ptz(accessToken, fvsDeviceDTO.getUsername(), fvsDeviceDTO.getChannelNo(), devicePtzOption.getValue(), 2000L);
    }

    @Override
    public FvsTokenDTO getToken(Integer deptId) {
        ImouApi imouApi = getImouApi(deptId);
        FvsTokenDTO fvsTokenDTO = new FvsTokenDTO();
        String accessToken = fvsTokenMgr.getImouAccessToken(imouApi, deptId);
        fvsTokenDTO.setToken(accessToken);
        fvsTokenDTO.setAppKey(imouApi.getAppKey());
        return fvsTokenDTO;
    }

    /**
     * 获取设备状态
     *
     * @param deptId       组织机构ID
     * @param deviceSerial 设备序列号
     * @param channelNo    通道号
     * @return 设备状态
     */
    public ImouDeviceInfo getDeviceInfo(Integer deptId, String deviceSerial, Integer channelNo) {
        ImouApi imouApi = getImouApi(deptId);
        String accessToken = fvsTokenMgr.getImouAccessToken(imouApi, deptId);
        return imouApi.getDeviceInfo(accessToken, deviceSerial, channelNo);
    }

    /**
     * 初始化token
     *
     * @param appKey    appKey
     * @param appSecret appSecret
     * @return token
     */
    public String initAccessToken(String appKey, String appSecret) {
        //乐橙云API 获取登录token
        ImouApi imouApi = new ImouApi(appKey, appSecret);
        return imouApi.getAccessToken();
    }

    /**
     * 删除设备
     *
     * @param fvsDeviceDTO 设备DTO
     */
    private void del(FvsDeviceDTO fvsDeviceDTO) {
        //获取登录token和设备序列号
        Integer deptId = fvsDeviceDTO.getDeptId();
        ImouApi imouApi = getImouApi(deptId);
        String accessToken = imouApi.getAccessToken();
        String deviceSerial = fvsDeviceDTO.getUsername();
        //从萤石云平台删除设备
        imouApi.delDevice(accessToken, deviceSerial);
    }


    /**
     * 初始化通道信息
     *
     * @param deviceId    设备ID
     * @param imouApi     大华API
     * @param accessToken token
     */
    private void initChannel(Integer deviceId, ImouApi imouApi, String accessToken) {
        FvsDevice fvsDevice = fvsDeviceMapper.selectByPrimaryKey(deviceId);
        if (fvsDevice == null) {
            return;
        }
        String deviceName = fvsDevice.getName();
        String deviceSerial = fvsDevice.getUsername();
        //获取直播通道列表
        List<ImouChannelInfo> channelList = imouApi.getChannelInfo(accessToken, deviceSerial);
        if (channelList == null || channelList.isEmpty()) {
            return;
        }
        for (ImouChannelInfo channelInfo : channelList) {
            //获取通道号
            Integer channelNo = Integer.valueOf(channelInfo.getChannelId());
            String statusStr = channelInfo.getStatus();
            int status = 0;
            if (ImouConstant.DEVICE_ONLINE_CODE.equals(statusStr)) {
                status = 1;
            }
            //多通道设备创建
            if (FvsDeviceType.DVR.getValue().equals(fvsDevice.getDeviceType())) {
                //创建设备
                FvsDevice device = new FvsDevice();
                BeanUtils.copyProperties(fvsDevice, device);
                device.setId(null);
                device.setPid(fvsDevice.getId());
                device.setDeviceType(FvsDeviceType.IPC.getValue());
                device.setChannelNo(channelNo);
                device.setDeviceStatus(status);
                device.setName(deviceName + ":" + channelNo);
                fvsDeviceMapper.insertSelective(device);
            } else {
                fvsDevice.setChannelNo(channelNo);
                fvsDevice.setDeviceStatus(status);
            }
            imouApi.startDevice(accessToken, deviceSerial, channelNo);
        }
        fvsDeviceMapper.updateByPrimaryKeySelective(fvsDevice);
    }


    /**
     * 获取乐橙API
     *
     * @param deptId 组织机构ID
     * @return 乐橙API
     */
    private ImouApi getImouApi(Integer deptId) {
        //获取当前组织机构的大华配置
        FvsSettingDTO fvsSetting = fvsTokenMgr.getFvsSetting(deptId, VsPlatform.DAHUA_IMOU);
        ImouApi imouApi = new ImouApi(fvsSetting.getAppKey(), fvsSetting.getAppSecret());
        fvsTokenMgr.getImouAccessToken(imouApi, deptId);
        return imouApi;
    }


}
